﻿using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Text.RegularExpressions;

namespace KorTransLib
{
    /// <summary>
    /// Türkiye'de 1:250000'den 1:2500'e kadar olan herhangi bir paftayı temsil eder.
    /// Kerem KAT
    /// </summary>
    public class Pafta
    {
        [DisplayName("Güneybatı Köşesi"), Description("Paftanın güneybatı köşe koordinatı.")]
        public Coordinate GüneyBatıKöşesi { get; set; }

        [DisplayName("Kuzeydoğu Köşesi"), Description("Paftanın kuzeydoğu köşe koordinatı.")]
        public Coordinate KuzeyDoğuKöşesi { get; set; }

        //private static Regex rePaftaAdı = new Regex("\\w+(?:-[A-R]\\d\\d(?:-[a-d](?:([1-4]|-\\d\\d(?:-[a-d](?:-[A-D])?)?)?)?)?)?", RegexOptions.Singleline);
        //private static Regex rePaftaAdı = new Regex(@"(?:\D+-)?(?:[A-R]\d\d(?:-[a-d](?:(?:[1-4]|-\d\d(?:-[a-d](?:-[A-D])?)?)?)?)?)?", RegexOptions.Singleline | RegexOptions.Compiled);
        private static Regex rePaftaAdı = new Regex(@"(?:\D+-)?(?<paftaKodu>[A-R]\d\d(?:-[a-d](?:(?:[1-4]|-\d\d(?:-[a-d](?:-[A-D])?)?)?)?)?)", RegexOptions.Singleline | RegexOptions.Compiled);

        private string paftaAdı;
        [DisplayName("Pafta Adı"), Description("Paftanın tanımlayıcı adı.")]
        public string PaftaAdı { get { return paftaAdı; } }

        private int ölçekSayısı;
        [DisplayName("Ölçek Sayısı"), Description("Paftanın ölçek sayısı.")]
        public int ÖlçekSayısı { get { return ölçekSayısı; } }

        private static Dictionary<string, Pafta> paftaIndex250000 = new Dictionary<string, Pafta>();
        private static Dictionary<string, Pafta> paftaSınır100000 = new Dictionary<string, Pafta>();

        static TypeConverter corconDMS = TypeDescriptor.GetConverter(typeof(DegreeMinuteSecondCoordinate));
        static TypeConverter corconDD = TypeDescriptor.GetConverter(typeof(DecimalDegreeCoordinate));
        static TypeConverter corconUTM = TypeDescriptor.GetConverter(typeof(UTMCoordinate));

        #region 250.000 lik pafta indeksi
        static Pafta()
        {
            paftaIndex250000.Add("EDİRNE", new Pafta(250000, new DecimalDegreeCoordinate(41, 25.5), new DecimalDegreeCoordinate(42, 27)));
            paftaIndex250000.Add("ÇANAKKALE", new Pafta(250000, new DecimalDegreeCoordinate(40, 25.5), new DecimalDegreeCoordinate(41, 27)));
            paftaIndex250000.Add("AYVALIK", new Pafta(250000, new DecimalDegreeCoordinate(39, 25.5), new DecimalDegreeCoordinate(40, 27)));
            paftaIndex250000.Add("URLA", new Pafta(250000, new DecimalDegreeCoordinate(38, 25.5), new DecimalDegreeCoordinate(39, 27)));
            paftaIndex250000.Add("KIRKLARELİ", new Pafta(250000, new DecimalDegreeCoordinate(41, 27), new DecimalDegreeCoordinate(42, 28.5)));
            paftaIndex250000.Add("BANDIRMA", new Pafta(250000, new DecimalDegreeCoordinate(40, 27), new DecimalDegreeCoordinate(41, 28.5)));
            paftaIndex250000.Add("BALIKESİR", new Pafta(250000, new DecimalDegreeCoordinate(39, 27), new DecimalDegreeCoordinate(40, 28.5)));
            paftaIndex250000.Add("İZMİR", new Pafta(250000, new DecimalDegreeCoordinate(38, 27), new DecimalDegreeCoordinate(39, 28.5)));
            paftaIndex250000.Add("AYDIN", new Pafta(250000, new DecimalDegreeCoordinate(37, 27), new DecimalDegreeCoordinate(38, 28.5)));
            paftaIndex250000.Add("MARMARİS", new Pafta(250000, new DecimalDegreeCoordinate(36, 27), new DecimalDegreeCoordinate(37, 28.5)));
            paftaIndex250000.Add("İSTANBUL", new Pafta(250000, new DecimalDegreeCoordinate(41, 28.5), new DecimalDegreeCoordinate(42, 30)));
            paftaIndex250000.Add("BURSA", new Pafta(250000, new DecimalDegreeCoordinate(40, 28.5), new DecimalDegreeCoordinate(41, 30)));
            paftaIndex250000.Add("KÜTAHYA", new Pafta(250000, new DecimalDegreeCoordinate(39, 28.5), new DecimalDegreeCoordinate(40, 30)));
            paftaIndex250000.Add("UŞAK", new Pafta(250000, new DecimalDegreeCoordinate(38, 28.5), new DecimalDegreeCoordinate(39, 30)));
            paftaIndex250000.Add("DENİZLİ", new Pafta(250000, new DecimalDegreeCoordinate(37, 28.5), new DecimalDegreeCoordinate(38, 30)));
            paftaIndex250000.Add("FETHİYE", new Pafta(250000, new DecimalDegreeCoordinate(36, 28.5), new DecimalDegreeCoordinate(37, 30)));
            paftaIndex250000.Add("EREĞLİ", new Pafta(250000, new DecimalDegreeCoordinate(41, 30), new DecimalDegreeCoordinate(42, 31.5)));
            paftaIndex250000.Add("ADAPAZARI", new Pafta(250000, new DecimalDegreeCoordinate(40, 30), new DecimalDegreeCoordinate(41, 31.5)));
            paftaIndex250000.Add("ESKİŞEHİR", new Pafta(250000, new DecimalDegreeCoordinate(39, 30), new DecimalDegreeCoordinate(40, 31.5)));
            paftaIndex250000.Add("AFYON", new Pafta(250000, new DecimalDegreeCoordinate(38, 30), new DecimalDegreeCoordinate(39, 31.5)));
            paftaIndex250000.Add("ISPARTA", new Pafta(250000, new DecimalDegreeCoordinate(37, 30), new DecimalDegreeCoordinate(38, 31.5)));
            paftaIndex250000.Add("ANTALYA", new Pafta(250000, new DecimalDegreeCoordinate(36, 30), new DecimalDegreeCoordinate(37, 31.5)));
            paftaIndex250000.Add("ZONGULDAK", new Pafta(250000, new DecimalDegreeCoordinate(41, 31.5), new DecimalDegreeCoordinate(42, 33)));
            paftaIndex250000.Add("BOLU", new Pafta(250000, new DecimalDegreeCoordinate(40, 31.5), new DecimalDegreeCoordinate(41, 33)));
            paftaIndex250000.Add("ANKARA", new Pafta(250000, new DecimalDegreeCoordinate(39, 31.5), new DecimalDegreeCoordinate(40, 33)));
            paftaIndex250000.Add("ILGIN", new Pafta(250000, new DecimalDegreeCoordinate(38, 31.5), new DecimalDegreeCoordinate(39, 33)));
            paftaIndex250000.Add("KONYA", new Pafta(250000, new DecimalDegreeCoordinate(37, 31.5), new DecimalDegreeCoordinate(38, 33)));
            paftaIndex250000.Add("ALANYA", new Pafta(250000, new DecimalDegreeCoordinate(36, 31.5), new DecimalDegreeCoordinate(37, 33)));
            paftaIndex250000.Add("KASTAMONU", new Pafta(250000, new DecimalDegreeCoordinate(41, 33), new DecimalDegreeCoordinate(42, 34.5)));
            paftaIndex250000.Add("ÇANKIRI", new Pafta(250000, new DecimalDegreeCoordinate(40, 33), new DecimalDegreeCoordinate(41, 34.5)));
            paftaIndex250000.Add("KIRŞEHİR", new Pafta(250000, new DecimalDegreeCoordinate(39, 33), new DecimalDegreeCoordinate(40, 34.5)));
            paftaIndex250000.Add("AKSARAY", new Pafta(250000, new DecimalDegreeCoordinate(38, 33), new DecimalDegreeCoordinate(39, 34.5)));
            paftaIndex250000.Add("KARAMAN", new Pafta(250000, new DecimalDegreeCoordinate(37, 33), new DecimalDegreeCoordinate(38, 34.5)));
            paftaIndex250000.Add("SİLİFKE", new Pafta(250000, new DecimalDegreeCoordinate(36, 33), new DecimalDegreeCoordinate(37, 34.5)));
            paftaIndex250000.Add("SİNOP", new Pafta(250000, new DecimalDegreeCoordinate(41, 34.5), new DecimalDegreeCoordinate(42, 36)));
            paftaIndex250000.Add("ÇORUM", new Pafta(250000, new DecimalDegreeCoordinate(40, 34.5), new DecimalDegreeCoordinate(41, 36)));
            paftaIndex250000.Add("YOZGAT", new Pafta(250000, new DecimalDegreeCoordinate(39, 34.5), new DecimalDegreeCoordinate(40, 36)));
            paftaIndex250000.Add("KAYSERİ", new Pafta(250000, new DecimalDegreeCoordinate(38, 34.5), new DecimalDegreeCoordinate(39, 36)));
            paftaIndex250000.Add("KOZAN", new Pafta(250000, new DecimalDegreeCoordinate(37, 34.5), new DecimalDegreeCoordinate(38, 36)));
            paftaIndex250000.Add("MERSİN", new Pafta(250000, new DecimalDegreeCoordinate(36, 34.5), new DecimalDegreeCoordinate(37, 36)));
            paftaIndex250000.Add("LAZKİYE", new Pafta(250000, new DecimalDegreeCoordinate(35, 34.5), new DecimalDegreeCoordinate(36, 36)));
            paftaIndex250000.Add("SAMSUN", new Pafta(250000, new DecimalDegreeCoordinate(41, 36), new DecimalDegreeCoordinate(42, 37.5)));
            paftaIndex250000.Add("TOKAT", new Pafta(250000, new DecimalDegreeCoordinate(40, 36), new DecimalDegreeCoordinate(41, 37.5)));
            paftaIndex250000.Add("SİVAS", new Pafta(250000, new DecimalDegreeCoordinate(39, 36), new DecimalDegreeCoordinate(40, 37.5)));
            paftaIndex250000.Add("ELBİSTAN", new Pafta(250000, new DecimalDegreeCoordinate(38, 36), new DecimalDegreeCoordinate(39, 37.5)));
            paftaIndex250000.Add("GAZİANTEP", new Pafta(250000, new DecimalDegreeCoordinate(37, 36), new DecimalDegreeCoordinate(38, 37.5)));
            paftaIndex250000.Add("ANTAKYA", new Pafta(250000, new DecimalDegreeCoordinate(36, 36), new DecimalDegreeCoordinate(37, 37.5)));
            paftaIndex250000.Add("HAMA", new Pafta(250000, new DecimalDegreeCoordinate(35, 36), new DecimalDegreeCoordinate(36, 37.5)));
            paftaIndex250000.Add("GİRESUN", new Pafta(250000, new DecimalDegreeCoordinate(40, 37.5), new DecimalDegreeCoordinate(41, 39)));
            paftaIndex250000.Add("DİVRİĞİ", new Pafta(250000, new DecimalDegreeCoordinate(39, 37.5), new DecimalDegreeCoordinate(40, 39)));
            paftaIndex250000.Add("MALATYA", new Pafta(250000, new DecimalDegreeCoordinate(38, 37.5), new DecimalDegreeCoordinate(39, 39)));
            paftaIndex250000.Add("URFA", new Pafta(250000, new DecimalDegreeCoordinate(37, 37.5), new DecimalDegreeCoordinate(38, 39)));
            paftaIndex250000.Add("SURUÇ", new Pafta(250000, new DecimalDegreeCoordinate(36, 37.5), new DecimalDegreeCoordinate(37, 39)));
            paftaIndex250000.Add("TRABZON", new Pafta(250000, new DecimalDegreeCoordinate(40, 39), new DecimalDegreeCoordinate(41, 40.5)));
            paftaIndex250000.Add("ERZİNCAN", new Pafta(250000, new DecimalDegreeCoordinate(39, 39), new DecimalDegreeCoordinate(40, 40.5)));
            paftaIndex250000.Add("ELAZIĞ", new Pafta(250000, new DecimalDegreeCoordinate(38, 39), new DecimalDegreeCoordinate(39, 40.5)));
            paftaIndex250000.Add("DİYARBAKIR", new Pafta(250000, new DecimalDegreeCoordinate(37, 39), new DecimalDegreeCoordinate(38, 40.5)));
            paftaIndex250000.Add("CEYLANPINAR", new Pafta(250000, new DecimalDegreeCoordinate(36, 39), new DecimalDegreeCoordinate(37, 40.5)));
            paftaIndex250000.Add("ARTVİN", new Pafta(250000, new DecimalDegreeCoordinate(41, 40.5), new DecimalDegreeCoordinate(42, 42)));
            paftaIndex250000.Add("AKÇAABAT", new Pafta(250000, new DecimalDegreeCoordinate(41, 39), new DecimalDegreeCoordinate(42, 40.5)));
            paftaIndex250000.Add("PERŞEMBE", new Pafta(250000, new DecimalDegreeCoordinate(41, 37.5), new DecimalDegreeCoordinate(42, 39)));
            paftaIndex250000.Add("TORTUM", new Pafta(250000, new DecimalDegreeCoordinate(40, 40.5), new DecimalDegreeCoordinate(41, 42)));
            paftaIndex250000.Add("ERZURUM", new Pafta(250000, new DecimalDegreeCoordinate(39, 40.5), new DecimalDegreeCoordinate(40, 42)));
            paftaIndex250000.Add("MUŞ", new Pafta(250000, new DecimalDegreeCoordinate(38, 40.5), new DecimalDegreeCoordinate(39, 42)));
            paftaIndex250000.Add("MARDİN", new Pafta(250000, new DecimalDegreeCoordinate(37, 40.5), new DecimalDegreeCoordinate(38, 42)));
            //paftaIndex250000.Add("ARDAHAN", new Pafta(250000, new DecimalDegreeCoordinate(42, 42), new DecimalDegreeCoordinate(41, 43.5)));
            paftaIndex250000.Add("ARDAHAN", new Pafta(250000, new DecimalDegreeCoordinate(41, 42), new DecimalDegreeCoordinate(42, 43.5)));
            paftaIndex250000.Add("KARS", new Pafta(250000, new DecimalDegreeCoordinate(40, 42), new DecimalDegreeCoordinate(41, 43.5)));
            paftaIndex250000.Add("KARAKÖSE", new Pafta(250000, new DecimalDegreeCoordinate(39, 42), new DecimalDegreeCoordinate(40, 43.5)));
            paftaIndex250000.Add("VAN", new Pafta(250000, new DecimalDegreeCoordinate(38, 42), new DecimalDegreeCoordinate(39, 43.5)));
            paftaIndex250000.Add("CİZRE", new Pafta(250000, new DecimalDegreeCoordinate(37, 42), new DecimalDegreeCoordinate(38, 43.5)));

            paftaIndex250000.Add("TİFLİS", new Pafta(250000, new DecimalDegreeCoordinate(41, 43.5), new DecimalDegreeCoordinate(42, 45)));
            paftaIndex250000.Add("ERİVAN", new Pafta(250000, new DecimalDegreeCoordinate(40, 43.5), new DecimalDegreeCoordinate(41, 45)));
            paftaIndex250000.Add("DOĞUBEYAZIT", new Pafta(250000, new DecimalDegreeCoordinate(39, 43.5), new DecimalDegreeCoordinate(40, 45)));
            paftaIndex250000.Add("BAŞKALE", new Pafta(250000, new DecimalDegreeCoordinate(38, 43.5), new DecimalDegreeCoordinate(39, 45)));
            paftaIndex250000.Add("ÇÖLEMERİK", new Pafta(250000, new DecimalDegreeCoordinate(37, 43.5), new DecimalDegreeCoordinate(38, 45)));
            paftaIndex250000.Add("ERBİL", new Pafta(250000, new DecimalDegreeCoordinate(36, 43.5), new DecimalDegreeCoordinate(37, 45)));

            paftaIndex250000.Add("MUSUL", new Pafta(250000, new DecimalDegreeCoordinate(36, 42), new DecimalDegreeCoordinate(37, 43.5)));
            paftaIndex250000.Add("HASEC", new Pafta(250000, new DecimalDegreeCoordinate(36, 40.5), new DecimalDegreeCoordinate(37, 42)));

            for (int i = 15; i <= 53; i++)
                paftaSınır100000.Add("D" + i.ToString(), Pafta.PaftaGetir("D" + i.ToString()));

            //paftaSınır100000.Add("D35", Pafta.PaftaGetir("D35"));
            //foreach (string s in paftaIndex250000.Keys)
            //{
            //    DecimalDegreeCoordinate dd = (DecimalDegreeCoordinate)TypeDescriptor.GetConverter(typeof(DecimalDegreeCoordinate)).ConvertFrom(paftaIndex250000[s].Merkez());
            //    int t1 = ((int)(dd.lat * 100)) * 10000 + (int)(dd.lon * 100);
            //    string hash = t1.ToString("X");                

            //    paftaHash.Add(s, hash);
            //}
        }
        #endregion

        public static List<string> paftaİsimleri()
        {
            List<string> ret = new List<string>(paftaIndex250000.Keys);
            return ret;
        }

        public enum AraYön
        {
            KuzeyBatı,
            GüneyDoğu,
            GüneyBatı,
            KuzeyDoğu
        }

        public Coordinate KöşeKoordinatı(AraYön köşe)
        {
            DecimalDegreeCoordinate ddGüneyBatı = (DecimalDegreeCoordinate)corconDD.ConvertFrom(GüneyBatıKöşesi);
            DecimalDegreeCoordinate ddKuzeyDoğu = (DecimalDegreeCoordinate)corconDD.ConvertFrom(KuzeyDoğuKöşesi);

            switch (köşe)
            {
                case AraYön.GüneyBatı:
                    return GüneyBatıKöşesi;
                    break;
                case AraYön.GüneyDoğu:
                    return new DecimalDegreeCoordinate(ddGüneyBatı.lat, ddKuzeyDoğu.lon);
                    break;
                case AraYön.KuzeyBatı:
                    return new DecimalDegreeCoordinate(ddKuzeyDoğu.lat, ddGüneyBatı.lon);
                    break;
                case AraYön.KuzeyDoğu:
                    return KuzeyDoğuKöşesi;
                    break;
            }
            return GüneyBatıKöşesi;
        }

        public Coordinate Merkez()
        {
            return (GüneyBatıKöşesi + KuzeyDoğuKöşesi) / 2.0;
        }

        private static bool KoordinatPaftaİçinde(Pafta p, Coordinate c)
        {
            DecimalDegreeCoordinate ddCoord = (DecimalDegreeCoordinate)TypeDescriptor.GetConverter(c).ConvertTo(c, typeof(DecimalDegreeCoordinate));
            DecimalDegreeCoordinate ddGüneyBatı = (DecimalDegreeCoordinate)TypeDescriptor.GetConverter(p.GüneyBatıKöşesi).ConvertTo(p.GüneyBatıKöşesi, typeof(DecimalDegreeCoordinate));
            DecimalDegreeCoordinate ddKuzeyDoğu = (DecimalDegreeCoordinate)TypeDescriptor.GetConverter(p.KuzeyDoğuKöşesi).ConvertTo(p.KuzeyDoğuKöşesi, typeof(DecimalDegreeCoordinate));

            if (ddCoord.lat >= ddGüneyBatı.lat
                && ddCoord.lat <= ddKuzeyDoğu.lat
                && ddCoord.lon >= ddGüneyBatı.lon
                && ddCoord.lon <= ddKuzeyDoğu.lon)
            {
                return true;
            }
            return false;
        }

        public bool KoordinatPaftaİçinde(Coordinate c)
        {
            return Pafta.KoordinatPaftaİçinde(this, c);
        }

        private static Pafta paftaBölümüBul(Pafta p, int enlemBölümü, int boylamBölümü, Coordinate coord, out int istenenEnlemBölümü, out int istenenBoylamBölümü)
        {
            for (int i = 0; i < enlemBölümü; i++)
                for (int j = 0; j < boylamBölümü; j++)
                {
                    Pafta pBölüm = Pafta.paftaBölümü(p, enlemBölümü, boylamBölümü, i, j);
                    if (KoordinatPaftaİçinde(pBölüm, coord))
                    {
                        istenenEnlemBölümü = i;
                        istenenBoylamBölümü = j;
                        return pBölüm;
                    }
                }
            istenenBoylamBölümü = 0;
            istenenEnlemBölümü = 0;
            return null;
        }

        private static Pafta paftaBölümü(Pafta p, int enlemBölümü, int boylamBölümü, int istenenEnlemBölümü, int istenenBoylamBölümü)
        {
            DecimalDegreeCoordinate ddGüneyBatı = (DecimalDegreeCoordinate)TypeDescriptor.GetConverter(p.GüneyBatıKöşesi).ConvertTo(p.GüneyBatıKöşesi, typeof(DecimalDegreeCoordinate));
            DecimalDegreeCoordinate ddKuzeyDoğu = (DecimalDegreeCoordinate)TypeDescriptor.GetConverter(p.KuzeyDoğuKöşesi).ConvertTo(p.KuzeyDoğuKöşesi, typeof(DecimalDegreeCoordinate));

            double enlemFarkı = ddKuzeyDoğu.lat - ddGüneyBatı.lat;
            double boylamFarkı = ddKuzeyDoğu.lon - ddGüneyBatı.lon;

            double güneyBatıEnlem = ddGüneyBatı.lat;
            double güneyBatıBoylam = ddGüneyBatı.lon;

            DecimalDegreeCoordinate GüneyBatıKöşesi = new DecimalDegreeCoordinate(güneyBatıEnlem + istenenEnlemBölümü * enlemFarkı / enlemBölümü, güneyBatıBoylam + istenenBoylamBölümü * boylamFarkı / boylamBölümü);

            DecimalDegreeCoordinate KuzeyDoğuKöşesi = new DecimalDegreeCoordinate(güneyBatıEnlem + (istenenEnlemBölümü + 1) * enlemFarkı / enlemBölümü, güneyBatıBoylam + (istenenBoylamBölümü + 1) * boylamFarkı / boylamBölümü);

            return new Pafta(0, GüneyBatıKöşesi, KuzeyDoğuKöşesi);
        }

        public static Pafta PaftaBul(int ÖlçekSayısı, Coordinate coord, out string PaftaAdı)
        {
            DecimalDegreeCoordinate dd = (DecimalDegreeCoordinate)corconDD.ConvertFrom(coord);

            if (dd.lon < 24 || dd.lon > 48 || dd.lat < 35 || dd.lat > 44)
                throw new System.ArgumentException("Pafta numarası bulunacak koordinat, Türkiye pafta sınırları içerisinde olmalıdır (24° D - 48° D, 35° K - 44° K).", "coord");

            int istenenEnlemBölümü;
            int istenenBoylamBölümü;

            switch (ÖlçekSayısı)
            {
                case 250000:
                    foreach (string s in paftaIndex250000.Keys)
                    {
                        Pafta p = paftaIndex250000[s];
                        if (KoordinatPaftaİçinde(p, coord))
                        {
                            PaftaAdı = s;
                            p.ölçekSayısı = ÖlçekSayısı;
                            return p;
                        }
                    }
                    break;

                case 100000:
                    Pafta p250000 = PaftaBul(250000, coord, out PaftaAdı);
                    Pafta ret100000;
                    if (p250000 == null)
                    {
                        foreach (string s in paftaSınır100000.Keys)
                        {
                            Pafta p = paftaSınır100000[s];
                            if (KoordinatPaftaİçinde(p, coord))
                            {
                                PaftaAdı = s;
                                p.ölçekSayısı = 100000;
                                return p;
                            }
                        }
                    }
                    else
                    {
                        ret100000 = paftaBölümüBul(p250000, 2, 3, coord, out istenenEnlemBölümü, out istenenBoylamBölümü);
                        DegreeMinuteSecondCoordinate dms = (DegreeMinuteSecondCoordinate)corconDMS.ConvertFrom(coord);
                        int doğu = dms.lonDegree * 2 - 36 + (dms.lonMinute >= 30 ? 1 : 0);
                        char kuzey = (char)((35 * 2 + 'R') - dms.latDegree * 2 - (dms.latMinute >= 30 ? 1 : 0));
                        PaftaAdı = string.Format("{0}-{1}{2}", PaftaAdı, kuzey, doğu);
                        ret100000.paftaAdı = PaftaAdı;
                        ret100000.ölçekSayısı = ÖlçekSayısı;
                        return ret100000;
                    }
                    break;
                case 50000:
                    Pafta p100000 = PaftaBul(100000, coord, out PaftaAdı);

                    Pafta ret50000 = paftaBölümüBul(p100000, 2, 2, coord, out istenenEnlemBölümü, out istenenBoylamBölümü);
                    PaftaAdı = string.Format("{0}-{1}", PaftaAdı,
                    istenenEnlemBölümü == 0 && istenenBoylamBölümü == 1 ? "c"
                        : istenenEnlemBölümü == 1 && istenenBoylamBölümü == 0 ? "a"
                        : istenenEnlemBölümü == 0 && istenenBoylamBölümü == 0 ? "d"
                        : istenenEnlemBölümü == 1 && istenenBoylamBölümü == 1 ? "b"
                        : "x"
                        );
                    ret50000.paftaAdı = PaftaAdı;
                    ret50000.ölçekSayısı = ÖlçekSayısı;
                    return ret50000;

                case 25000:
                    Pafta p50000 = PaftaBul(50000, coord, out PaftaAdı);

                    Pafta ret25000 = paftaBölümüBul(p50000, 2, 2, coord, out istenenEnlemBölümü, out istenenBoylamBölümü);
                    PaftaAdı = string.Format("{0}{1}", PaftaAdı,
                    istenenEnlemBölümü == 0 && istenenBoylamBölümü == 1 ? "3"
                        : istenenEnlemBölümü == 1 && istenenBoylamBölümü == 0 ? "1"
                        : istenenEnlemBölümü == 0 && istenenBoylamBölümü == 0 ? "4"
                        : istenenEnlemBölümü == 1 && istenenBoylamBölümü == 1 ? "2"
                        : "0"
                        );
                    ret25000.paftaAdı = PaftaAdı;
                    ret25000.ölçekSayısı = ÖlçekSayısı;
                    return ret25000;
                case 10000:
                    Pafta p50000r = PaftaBul(50000, coord, out PaftaAdı);

                    Pafta ret10000 = paftaBölümüBul(p50000r, 5, 5, coord, out istenenEnlemBölümü, out istenenBoylamBölümü);
                    PaftaAdı = string.Format("{0}-{1}", PaftaAdı, (istenenBoylamBölümü - 5 * istenenEnlemBölümü + 21).ToString("00"));
                    ret10000.paftaAdı = PaftaAdı;
                    ret10000.ölçekSayısı = ÖlçekSayısı;
                    return ret10000;
                case 5000:
                    Pafta p10000 = PaftaBul(10000, coord, out PaftaAdı);
                    Pafta ret5000 = paftaBölümüBul(p10000, 2, 2, coord, out istenenEnlemBölümü, out istenenBoylamBölümü);
                    PaftaAdı = string.Format("{0}-{1}", PaftaAdı,
                    istenenEnlemBölümü == 0 && istenenBoylamBölümü == 1 ? "c"
                        : istenenEnlemBölümü == 1 && istenenBoylamBölümü == 0 ? "a"
                        : istenenEnlemBölümü == 0 && istenenBoylamBölümü == 0 ? "d"
                        : istenenEnlemBölümü == 1 && istenenBoylamBölümü == 1 ? "b"
                        : "x"
                        );
                    ret5000.paftaAdı = PaftaAdı;
                    ret5000.ölçekSayısı = ÖlçekSayısı;
                    return ret5000;
                case 2500:
                    Pafta p5000 = PaftaBul(5000, coord, out PaftaAdı);
                    Pafta ret2500 = paftaBölümüBul(p5000, 2, 2, coord, out istenenEnlemBölümü, out istenenBoylamBölümü);
                    PaftaAdı = string.Format("{0}-{1}", PaftaAdı,
                    istenenEnlemBölümü == 0 && istenenBoylamBölümü == 1 ? "C"
                        : istenenEnlemBölümü == 1 && istenenBoylamBölümü == 0 ? "A"
                        : istenenEnlemBölümü == 0 && istenenBoylamBölümü == 0 ? "D"
                        : istenenEnlemBölümü == 1 && istenenBoylamBölümü == 1 ? "B"
                        : "x"
                        );
                    ret2500.paftaAdı = PaftaAdı;
                    ret2500.ölçekSayısı = ÖlçekSayısı;
                    return ret2500;
                default:
                    break;
            }

            PaftaAdı = "";
            return null;
        }

        private static string GetPaftaAdı(string PaftaAdı, out bool geçerli)
        {
            bool paftaAdındaRakamVar = false;
            foreach (char c in PaftaAdı)
                if (char.IsDigit(c))
                {
                    paftaAdındaRakamVar = true;
                    break;
                }

            MatchCollection mc = rePaftaAdı.Matches(PaftaAdı);
            if (mc.Count >= 1 && mc[0].Length == PaftaAdı.Length)
            {
                foreach (Match m in mc)
                {
                    if (m.Groups["paftaKodu"].Value.Length > 0)
                    {
                        geçerli = true;
                        return m.Groups["paftaKodu"].Value;
                    }
                }
            }
            if (!PaftaAdı.Contains("-") && !paftaAdındaRakamVar)
            {
                geçerli = true;
                return PaftaAdı;
            }
            geçerli = false;
            return string.Empty;
        }

        public static Pafta PaftaGetir(string PaftaAdı)
        {
            bool paftaAdıGeçerli = false;
            PaftaAdı = GetPaftaAdı(PaftaAdı, out paftaAdıGeçerli);
            if (!paftaAdıGeçerli)
                throw new ArgumentException("Pafta Adı yanlış veya 250.000, 100.000, 50.000, 25.000, 10.000, 5.000, 2.500 ölçekli değil.", PaftaAdı);

            // PaftaAdı: İSTANBUL-F22-b3
            bool geçersiz = false;
            Pafta ret;
            string s250000;

            if (PaftaAdı.IndexOf("-") > 0)
            {
                s250000 = PaftaAdı.Substring(0, PaftaAdı.IndexOf("-"));
            }
            else
            {
                s250000 = PaftaAdı;
            }

            if (!paftaIndex250000.ContainsKey(s250000))
            // 250000lik pafta adı yoksa
            {
                int res;
                if (char.IsLetter(PaftaAdı.Substring(0, 1)[0]) && int.TryParse(PaftaAdı.Substring(1, 2), out res))
                {
                    // 250000lik pafta adını bul:
                    // pafta içerisinde bir koordinat belirle ve bu koordinatın paftasını bulan fonksiyonu çağır
                    double kuzey = ((35 * 2 + 'R') - PaftaAdı.Substring(0, 1)[0]) / 2.0;

                    double doğu = res / 2.0 + 18;

                    s250000 = "TEST";
                    Pafta.PaftaBul(250000, new DecimalDegreeCoordinate(kuzey, doğu), out s250000);
                    if (s250000.Length > 0)
                        PaftaAdı = s250000 + '-' + PaftaAdı;
                    // (kuzey - ddGüneyBatı.lat)  = 0.5 demek 1. enlem demek 0. değil.
                    //kuzey = (kuzey - ddGüneyBatı.lat) * 2;
                    //doğu = (doğu - ddGüneyBatı.lon) * 2;
                }
                else
                {
                    throw new ArgumentException("Pafta Adı yanlış veya 250.000, 100.000, 50.000, 25.000, 10.000, 5.000, 2.500 ölçekli değil.", PaftaAdı);
                }
            }

            ret = paftaIndex250000[s250000];
            ret.ölçekSayısı = 250000;

            if (PaftaAdı.IndexOf("-") > 0)
            {
                string paftaRem = PaftaAdı.Substring(s250000.Length + 1);
                //100000lik

                //int doğu = dms.lonDegree * 2 - 36 + (dms.lonMinute >= 30 ? 1 : 0);
                //char kuzey = (char)((35 * 2 + 'R') - dms.latDegree * 2 - (dms.latMinute >= 30 ? 1 : 0));
                double kuzey = ((35 * 2 + 'R') - paftaRem[0]) / 2.0;

                double doğu = double.Parse(paftaRem.Substring(1, 2)) / 2.0 + 18;


                DecimalDegreeCoordinate ddGüneyBatı = (DecimalDegreeCoordinate)corconDD.ConvertFrom(ret.GüneyBatıKöşesi);
                // (kuzey - ddGüneyBatı.lat)  = 0.5 demek 1. enlem demek 0. değil.
                kuzey = (kuzey - ddGüneyBatı.lat) * 2;
                doğu = (doğu - ddGüneyBatı.lon) * 2;

                ret = paftaBölümü(ret, 2, 3, (int)kuzey, (int)doğu);
                ret.ölçekSayısı = 100000;

                if (paftaRem.IndexOf("-") > 0)
                {
                    paftaRem = paftaRem.Substring(paftaRem.IndexOf("-") + 1);
                    if (paftaRem.Length >= 1)
                    {
                        // 50000lik
                        char c50000 = paftaRem[0];

                        ret = paftaBölümü(ret, 2, 2, c50000 == 'a' || c50000 == 'b' ? 1 : 0, c50000 == 'c' || c50000 == 'b' ? 1 : 0);
                        ret.ölçekSayısı = 50000;
                        if (paftaRem.Length > 2)
                            paftaRem = paftaRem.Substring(2);
                        if (paftaRem.Length >= 2)
                        {
                            if (char.IsDigit(paftaRem[0]))
                            {
                                int i10000 = int.Parse(paftaRem.Substring(0, 2));
                                //10000 veya daha küçük
                                // boylam - 5 enlem + 21
                                ret = paftaBölümü(ret, 5, 5, 5 - (i10000 - 21 + 25) / 5, (i10000 - 21 + 25) % 5);
                                ret.ölçekSayısı = 10000;

                                if (paftaRem.IndexOf("-") > 0)
                                {
                                    paftaRem = paftaRem.Substring(paftaRem.IndexOf("-") + 1);
                                    //5000 veya daha küçük
                                    char c5000 = paftaRem[0];
                                    ret = paftaBölümü(ret, 2, 2, c5000 == 'a' || c5000 == 'b' ? 1 : 0, c5000 == 'c' || c5000 == 'b' ? 1 : 0);
                                    ret.ölçekSayısı = 5000;

                                    if (paftaRem.IndexOf("-") > 0)
                                    {
                                        paftaRem = paftaRem.Substring(paftaRem.IndexOf("-") + 1);
                                        //2500
                                        char c2500 = paftaRem[0];
                                        ret = paftaBölümü(ret, 2, 2, c2500 == 'A' || c5000 == 'B' ? 1 : 0, c5000 == 'C' || c5000 == 'D' ? 1 : 0);
                                        ret.ölçekSayısı = 2500;
                                    }
                                }
                            }
                            else
                            {
                                //25000
                                char c25000 = paftaRem[1];
                                ret = paftaBölümü(ret, 2, 2, c25000 == '1' || c25000 == '2' ? 1 : 0, c25000 == '3' || c25000 == '2' ? 1 : 0);
                                ret.ölçekSayısı = 25000;
                            }
                        }
                        else
                        {
                            ret.paftaAdı = PaftaAdı;
                            return ret;
                        }
                    }
                    else
                    {
                        geçersiz = true;
                    }
                }
            }

            if (geçersiz)
                throw new ArgumentException("Pafta Adı yanlış veya 250.000, 100.000, 50.000, 25.000, 10.000, 5.000, 2.500 ölçekli değil.");
            ret.paftaAdı = PaftaAdı;
            return ret;
        }

        public Pafta(int ÖlçekSayısı, Coordinate GüneyBatıKöşesi, Coordinate KuzeyDoğuKöşesi)
        {
            this.ölçekSayısı = ÖlçekSayısı;
            this.GüneyBatıKöşesi = GüneyBatıKöşesi;
            this.KuzeyDoğuKöşesi = KuzeyDoğuKöşesi;
            PaftaBul(ÖlçekSayısı, this.Merkez(), out paftaAdı);
        }
    }
}